package tk.sunlatus.project.config;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.configuration.AbstractFileConfiguration;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.apache.log4j.Logger;
import org.springframework.core.io.Resource;
import org.springframework.web.context.support.ServletContextResource;

import tk.sunlatus.project.config.domain.ConfigFile;


public final class ConfigurationManager extends ConfigurationHolder {
    
    private static final Logger LOGGER = Logger.getLogger(ConfigurationManager.class);

    /**
     * 根据文件key获取配置信息
     * 
     * @param cfgFileKey
     * @return
     */
    public Configuration getConfiguration(String cfgFileKey) {
        Configuration result = null;
        result = getConfiguration(cfgFileKey, ConfigerType.NoRefresh.getType());
        if (result == null) {
            result = getConfiguration(cfgFileKey, ConfigerType.RefreshOnUsed.getType());
            reload(cfgFileKey, result, ConfigFile.RefreshType.RERESH_REAL_TIME);
        }
        if (result == null) {
            result = getConfiguration(cfgFileKey, ConfigerType.RefreshByTask.getType());
        }
        return result;
    }

    /**
     * 重新加载配置信息
     * 
     * @param result
     */
    private void reload(String key, Configuration config, String refreshType) {

        if ((isTest() || ConfigFile.RefreshType.RERESH_REAL_TIME.equals(refreshType)) && checkNeedReload(key, config)) {
            ((AbstractFileConfiguration) config).reload();
        }

    }

    private boolean checkNeedReload(String fileKey, Configuration config) {
        boolean result = false;
        if (config instanceof AbstractFileConfiguration) {
            try {
                ConfigFile cfgFile = getConfigFiles().get(fileKey);
                if (cfgFile != null) {
                    URL url = getServletContext().getResource(cfgFile.getPath());
                    String filePath = url.getFile();
                    Resource resource = new ServletContextResource(getServletContext(), filePath);
                    File file = resource.getFile();
                    long lastModified = file.lastModified();
                    result = lastModified > cfgFile.getLastModify();
                    if (result || lastModified != cfgFile.getLastModify()) {
                        cfgFile.setLastModify(lastModified);
                    }
                }
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 根据配置类型和配置文件key获取配置信息
     * 
     * @param cfgFileKey
     *            配置文件key
     * @param type
     *            刷新类型
     * @return 配置信息
     */
    public Configuration getConfiguration(String cfgFileKey, int type) {
        ConfigerType configerType = ConfigerType.getConfigerType(type);
        switch (configerType) {
        case NoRefresh:
            return getCfgNoRefresh().get(cfgFileKey);
        case RefreshOnUsed:
            return getCfgRefreshOnUsered().get(cfgFileKey);
        case RefreshByTask:
            return getCfgRefreshByTask().get(cfgFileKey);
        default:
            return null;
        }
    }

    /**
     * 获取所有配置信息
     * 
     * @return
     */
    public List<Configuration> getCofigurationList() {
        List<Configuration> configurationList = new ArrayList<Configuration>();
        configurationList.addAll(getConfigurations(getCfgNoRefresh()));
        configurationList.addAll(getConfigurations(getCfgRefreshOnUsered()));
        configurationList.addAll(getConfigurations(getCfgRefreshByTask()));
        return configurationList;
    }

    /**
     * 从指定的缓存类型中获取配置信息
     * 
     * @param configurationMap
     * @return
     */
    private List<Configuration> getConfigurations(Map<String, Configuration> configurationMap) {
        // TODO log
        LOGGER.debug(getClass().getName() + ".getConfigurations() begin...");
        LOGGER.debug(getClass().getName() + ".getConfigurations() begin...");
        LOGGER.debug("\tmethod args:{configurationMap[type:Map<String, AbstractFileConfiguration>; value:"
                + ReflectionToStringBuilder.toString(configurationMap) + "]}");
        LOGGER.debug("\tmethod args:{configurationMap[type:Map<String, AbstractFileConfiguration>; value:"
                + ReflectionToStringBuilder.toString(configurationMap) + "]}");
        List<Configuration> configurationList = new ArrayList<Configuration>();
        Configuration cfg = null;
        for (Entry<String, Configuration> entry : configurationMap.entrySet()) {
            cfg = entry.getValue();
            if (configurationMap != null) {
                configurationList.add(cfg);
            }
        }
        LOGGER.debug(getClass().getName() + ".getConfigurations() end.");
        LOGGER.debug("method result:{type:List<Configuration>; value:" + ReflectionToStringBuilder.toString(configurationMap) + "}");
        return configurationList;
    }

    /**
     * 重新加载配置文件
     */
    public void reload() {
        // TODO log
        LOGGER.debug("reload configurations begin...");

        Map<String, Configuration> configurations = getCfgRefreshByTask();
        for (Entry<String, Configuration> entry : configurations.entrySet()) {
            if (checkNeedReload(entry.getKey(), entry.getValue())) {
                LOGGER.debug(" configuration " + entry.getKey() + " reloading ...");
//TODO                entry.getValue().reload();
                LOGGER.debug(" configuration " + entry.getKey() + " reload success.");
            }
        }
        LOGGER.debug("reload configurations success.");
    }

    /**
     * 重新加载所有除实时加载的配置文件
     */
    public void reloadAll() {
        LOGGER.debug("reload all configuration begin...");
        Map<String, Configuration> configurations = new ConcurrentHashMap<String, Configuration>();
        configurations.putAll(getCfgNoRefresh());
        configurations.putAll(getCfgRefreshByTask());
        for (Entry<String, Configuration> entry : configurations.entrySet()) {
            if (checkNeedReload(entry.getKey(), entry.getValue())) {
                LOGGER.debug("\treload " + entry.getKey() + " ...");
// TODO               entry.getValue().reload();
                LOGGER.debug("\treload " + entry.getKey() + " success.");
            }
        }
        LOGGER.debug("reload all configuration success.");
    }
}
